/**
 * 
 */
package org.zgstudio.ddlchecker;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author zhguo
 * 
 */
public class ResultChecker implements Runnable {
    private List<LinkCheckListener> listeners = new ArrayList<LinkCheckListener>();

    private List<LinkCheckResult>   results   = new LinkedList<LinkCheckResult>();

    private List<LinkCheckResult>   shadow    = new LinkedList<LinkCheckResult>();

    private ReentrantLock           lock      = new ReentrantLock();

    public void registerListener(LinkCheckListener listener) {
        listeners.add(listener);
    }

    private boolean              started   = false;
    private boolean              completed = false;
    private static ResultChecker rc        = null;

    private ResultChecker() {
    }

    public static ResultChecker getInstance() {
        if (rc == null)
            rc = new ResultChecker();
        return rc;
    }

    public boolean completes() {
        if (!started)
            return false;
        return isCompleted();
    }

    private ScheduledExecutorService exeServ;

    public void startChecking() {
        for (Iterator<LinkCheckListener> it = listeners.iterator(); it
                .hasNext();) {
            it.next().linkCheckStart();
        }
        
        exeServ = Executors.newSingleThreadScheduledExecutor();
        started = true;
        exeServ.scheduleAtFixedRate(ResultChecker.getInstance(), 0, 500,
                TimeUnit.MILLISECONDS);
    }

    public synchronized void run() {
        swap();
        if (!results.isEmpty()) {
            for (Iterator<LinkCheckResult> it = results.iterator(); it
                    .hasNext();) {
                LinkCheckResult result = it.next();
                for (Iterator<LinkCheckListener> it2 = listeners.iterator(); it2
                        .hasNext();) {
                    it2.next().singleLinkCheckComplete(result);
                }
            }
        }
        results.clear();

        if (completes()) {
            for (Iterator<LinkCheckListener> it = listeners.iterator(); it
                    .hasNext();) {
                it.next().linkCheckAllComplete();
            }
            exeServ.shutdown();
        }
    }

    private void swap() {
        lock.lock();
        try {
            List<LinkCheckResult> temp = shadow;
            shadow = results;
            results = temp;
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void addNewResult(LinkCheckResult result) {
        lock.lock();
        try {
            shadow.add(result);
        } catch (Exception ex) {
            ex.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void setCompleted(boolean completed) {
        this.completed = completed;
    }

    public boolean isCompleted() {
        return completed;
    }
}
